<template>
  <div style="display: flex; height: 100%; flex: 1;">
    <HierarchyList :pagination="pagination" :columns="columns" :load-data="loadData"
                   ref="refHiMenu" :search-form="searchForms" :create-label="addMenuLabel"
                   :export-label="exportLabel" :export-asset="doExportMenus"
                   :import-label="importLabel" :import-asset="importMenus"
                   :filter-action="true" :filter-data="filterData"
                   :add-item="addMenu" :hidePageable="true"/>
    <EditDialog ref="refEditDlg" :columns="columns" :rules="rules" :submit="onSubmit"
                :form-label-width="100" :is-show-dialog="false"/>
    <ImportDataDialog ref="refImport" url="/uni-center/v1/excel/asset/import/type"
                      :tips="'是否更新已经存在的菜单数据'" :do-upload="uploadAction"
                      :root-tips="'导入菜单根节点'"/>
  </div>
</template>

<script setup lang="ts">

import {computed, nextTick, reactive, ref} from "vue";
import {currentNames, TYPES} from "@/stores/conf";
import {loadAssetLevel, setMenuToHome} from "@/apis/sop";
import {requestForm} from "@/apis/request";
import HierarchyList from "@/views/sop/list/HierarchyList.vue";
import {msgConfirm, msgError, msgInfo, showInfo} from "@/utils/InfoUtil";
import EditDialog from "@/components/common/EditDialog.vue";
import {computeTreeData, findTreeParent} from "@/utils/DataTreeUtil";
import {buildAsset} from "@/utils/sop/DataUtil";
import {useCurrent} from "@/utils/sop/UseCurrentFunc";
import {exportAssetByType, filterTreeList, handleLevelData} from "@/utils/SystemUtil";
import {useStore} from "@/stores";
import {useAssetOp} from "@/utils/sop/UseAssetOp";
import ImportDataDialog from "@/widget/ImportDataDialog.vue";
import {hasMenuPermit} from "@/utils/sop/PermitUtil";
import {filterNameInput} from "@/utils/StrUtil";

const props = withDefaults(defineProps<{
  entry: any,
}>(), {});

const store = useStore();
const refEditDlg = ref();
const refHiMenu = ref();
const refImport = ref();
const currentItem = ref<any>();
const menuData = ref([]);
const parentId = ref('');

const {updateCurrent, current} = useCurrent(currentNames.MENU);
const {doSaveAsset, doDeleteAsset} = useAssetOp(props.entry);

const rules = reactive({
  name: [{required: true, message: '请输入菜单名称', trigger: ['blur']},],
})

const addMenuLabel = computed(() => {
  return hasMenuPermit('asset:menu:add') ? '新增菜单' : '';
})

const importLabel = computed(() => {
  return hasMenuPermit('asset:menu:import') ? '导入' : '';
})

const exportLabel = computed(() => {
  return hasMenuPermit('asset:menu:export') ? '导出' : '';
})

const getSearchItems = () => {
  const searchItems = [];
  searchItems.push({
    type: 'input',
    name: 'name',
    label: `菜单名称`,
    size: 'default',
    placeholder: `请输入菜单名称`,
    clearable: true,
    defValue: '',
    width: '200px',
  });

  return searchItems;
}

const searchForms = ref(getSearchItems());

const filterData = async (data: any, params: string) => {
  if (!params || !params.name) {
    return data;
  }
  return filterTreeList(data, (item: any) => {
    return item.name.indexOf(params.name) != -1 ? 1 : 2;
  });
}

const uploadAction = async (option: any, url: any, headers: any) => {
  const platform: any = store.getCurrentPlatform();
  let formData: any = new FormData();
  formData.append("file", option.file);
  formData.append("assetType", TYPES.MENU);
  formData.append("platformId", platform.id);
  if (parentId.value) {
    formData.append("parentId", parentId.value);
  }

  parentId.value = '';

  await requestForm({
    url: url,
    method: 'post',
    headers: headers,
    data: formData,
  });
  refresh();
}

const loadData = async (params: any) => {
  const platform: any = store.getCurrentPlatform();

  const result = await loadAssetLevel({
    server: props.entry.server,
    targetId: platform.id,
    assetType: TYPES.MENU,
    ...params,
  });

  if (result && result.data) {
    menuData.value = [];
    handleLevelData(menuData.value, result.data, menuProps);
    delete result.data;
    result.data = {};
    result.data.data = menuData.value;
  } else {
    menuData.value = [];
  }

  return result;
}

const importMenus = () => {
  refImport.value.handleImport();
}

const exportMenus = async (parentId: string = '') => {
  const platform: any = store.getCurrentPlatform();

  await exportAssetByType({
    platformId: platform.id,
    assetType: TYPES.MENU,
    parentId: parentId,
  }, `${TYPES.MENU}_${new Date().getTime()}.xlsx`, {});
}

const doExportMenus = async () => {
  const platform: any = store.getCurrentPlatform();

  await exportAssetByType({
    platformId: platform.id,
    assetType: TYPES.MENU,
  }, `${TYPES.MENU}_${new Date().getTime()}.xlsx`, {});
}

const refresh = () => {
  nextTick(() => refHiMenu.value?.refresh(current()))
}

const checkSubmit = (item: Record<string, any>, editType: string) => {
  if ('add' !== editType) {
    const parent: MenuType | undefined = findTreeParent(menuData.value, item);
    if (parent) {
      if (item.menuType === 2 && parent.menuType !== 1) {
        msgError('按钮类型菜单项父菜单类型错误');
        return false;
      } else if (item.menuType === 1 && parent.menuType !== 0) {
        msgError('菜单项父菜单类型错误');
        return false;
      } else if (item.menuType === 0 && parent.menuType !== 0) {
        msgError('目录类型菜单项父菜单类型错误');
        return false;
      }
    }
  }
  return true;
}

const menuProps: any = [
  'icon',
  'openMode',
  'hidden',
  'routeName',
  'routePath',
  'level',
  'component',
  'menuType',
  'keepAlive'
]

const onSubmit = async (item: Record<string, any>, editType: string) => {
  const platform: any = store.getCurrentPlatform();
  let assetInfo = buildAsset(item, 'MENU', {
    icon: item.menuIcon || item.icon,
    openMode: item.openMode,
    hidden: item.hidden,
    routeName: item.routeName,
    routePath: item.routePath,
    level: item.level,
    component: item.component,
    menuType: item.menuType,
    keepAlive: item.keepAlive,
  });

  if (item.isHome) {
    assetInfo.props['isHome'] = true;
  }

  if (item.menuType == 0) {
    assetInfo.subType = "DIR";
  } else if (item.menuType == 1) {
    assetInfo.isLeaf = 1;
    assetInfo.subType = "MENU";
  } else if (item.menuType == 2) {
    assetInfo.subType = "BUTTON";
  }

  assetInfo.classify = "TREE";

  if (checkSubmit(item, editType)) {
    const result = await doSaveAsset(platform.id, assetInfo);

    if (result.code === 0) {
      msgInfo('保存菜单成功！');
      setTimeout(() => refresh(), 300);
    } else {
      msgError(result.message);
    }

    return result;
  }
}

const handleMenuTypeChanged = (cols: any, val: any) => {
  let canEdit: boolean = true;
  if (val == 2) {
    canEdit = false;
  }
  cols[4].canEdit = canEdit;
  cols[5].canEdit = canEdit;
  cols[6].canEdit = val == 1 || val == 0;
  cols[7].canEdit = val == 1;
  cols[9].canEdit = canEdit;
  cols[10].canEdit = canEdit;
  cols[11].canEdit = canEdit;
  cols[12].canEdit = canEdit;
}

const getMenuTypeOptions = (isAdd: any) => {
  let options: any = [
    {
      value: 0,
      label: '目录'
    },
    {
      value: 1,
      label: '菜单'
    },
  ];
  if (!isAdd) {
    options.push({
      value: 2,
      label: '按钮'
    });
  }
  return options;
}

const deleteMenu = async (row: any) => {
  if (row.children && row.children.length != 0) {
    showInfo('请先删除菜单子菜单！');
  } else {
    const result = await doDeleteAsset(getTargetId(), row);
    if (result.code === 0) {
      msgInfo('删除菜单成功！');
      setTimeout(() => refresh(), 300);
    } else {
      msgError(result.message ? result.message : '删除菜单失败！');
    }
  }
}

const findHomeMenu = (menus: any) => {
  for (let i = 0; i < menus.length; ++i) {
    const menu: any = menus[i];
    if (menu.isHome) {
      return menu;
    }
    if (menu.children && menu.children.length > 0) {
      const homeMenu: any = findHomeMenu(menu.children);
      if (homeMenu) {
        return homeMenu;
      }
    }
  }
  return undefined;
}

const setMenuAsHome = async (row: any) => {
  const homeMenu = findHomeMenu(menuData.value);
  if (!homeMenu || homeMenu.id != row.id) {
    const platform: any = store.getCurrentPlatform();
    const result = await setMenuToHome({
      menuId: row.id,
      platformId: platform.id,
    });
    if (result.code === 0) {
      msgInfo('设置菜单为首页成功！');
      setTimeout(() => refresh(), 300);
    } else {
      msgError(result.message ? result.message : '设置菜单为首页失败！');
    }
  }
}

const newMenu = () => {
  return {
    state: 1,
    hidden: 0,
    level: 1,
    openMode: 1,
    menuType: 1,
    keepAlive: 1,
    type: TYPES.MENU,
  };
}

const pagination = ref({
  current: 1,
  pageSize: 20,
  total: 0,
});

const getTargetId = () => {
  return '';
}

const buildMenuOperations = (row: any) => {
  const operations: any = [];
  if (hasMenuPermit('asset:menu:add')) {
    operations.push({
      name: '新增',
      disabled: (row: any): boolean => {
        return row.menuType === 2 || row.noAuth == 1;
      },
      callback: (data: any, row: any): void => {
        const parent = row;

        if (parent.menuType === 0 || parent.menuType === 1) {
          currentItem.value = newMenu();
          currentItem.value.disabled = true;
          currentItem.value.parentId = parent.id;
          currentItem.value.treeData = [
            {
              value: parent.id,
              label: parent.name,
            }
          ]

          if (parent.menuType === 0) {
            currentItem.value.menuType = 1;
            columns.value[3].readOnly = false;
            columns.value[3].options = getMenuTypeOptions(true);
          } else {
            currentItem.value.menuType = 2;
            columns.value[3].readOnly = false;
            columns.value[3].options = getMenuTypeOptions(false);
            columns.value[3].options?.shift();
          }

          handleMenuTypeChanged(columns.value, currentItem.value.menuType);

          refEditDlg.value?.editAdd('新增菜单', currentItem.value);
        } else {
          console.log('---- 当前菜单不是类型错误:', parent.menuType);
        }
      }
    });
  }
  if (hasMenuPermit('asset:menu:edit')) {
    operations.push({
      name: '编辑',
      disabled: (row: any) => {
        return row.noAuth == 1;
      },
      callback: (data: any, row: any): void => {
        const treeData = computeTreeData(data, row, (item: any) => item.menuType !== 0);
        currentItem.value = row;
        currentItem.value.treeData = treeData.data;

        if (row.menuType !== 2) {
          columns.value[3].readOnly = false;
          columns.value[3].options = getMenuTypeOptions(true);
        } else {
          columns.value[3].readOnly = true;
          columns.value[3].options = getMenuTypeOptions(false);
        }

        handleMenuTypeChanged(columns.value, row.menuType);

        refEditDlg.value?.editUpdate('编辑菜单', row);
      }
    });
  }
  operations.push({
    type: 'dropdown',
    name: '更多',
    doCommand: async (option: any) => {
      const {command, row} = option;
      if (command == 'import') {
        parentId.value = row.id;
        importMenus();
      } else if (command == 'export') {
        await exportMenus(row.id);
      } else if (command == 'delete') {
        msgConfirm("是否确定删除菜单？", async () => {
          await deleteMenu(row);
        })
      } else if (command == 'asHome') {
        await setMenuAsHome(row);
      }
    },
    downItems: [{
      command: 'import',
      label: '导入',
      disabled: (row: any): boolean => {
        return row.menuType !== 0 || row.noAuth == 1 ||
            !hasMenuPermit('asset:menu:import');
      },
    },
    {
      command: 'export',
      label: '导出',
      disabled: (row: any): boolean => {
        return row.menuType !== 0 || row.noAuth == 1 ||
            !hasMenuPermit('asset:menu:export');
      },
    },
    {
      command: 'delete',
      label: '删除',
      disabled: (row: any): boolean => {
        return row.noAuth == 1 ||
            !hasMenuPermit('asset:menu:delete');
      },
    },
    {
      command: 'asHome',
      label: '设为首页',
      disabled: (row: any): boolean => {
        return row.menuType !== 1 || row.noAuth == 1;
      },
    }]
  });

  return operations;
}

const columns = ref([
  {
    id: 'id',
    name: '菜单标识',
    hideCol: true,
    show: false,
    canEdit: false,
  },
  {
    id: 'parentId',
    name: '父菜单',
    type: 'tree',
    show: false,
    hideCol: true,
    canEdit: true,
    readOnly: true,
    treeKey: 'parentName'
  },
  {
    id: 'name',
    name: '菜单名称',
    sort: 'custom',
    show: true,
    offset: '16px',
    align: 'left',
    headAlign: 'left',
    canAction: (row: any) => {
      return row.noAuth != 1;
    },
    action: (data: any, row: any) => {
      updateCurrent({type: TYPES.MENU, ...row})
    }
  },
  {
    id: 'menuType',
    name: '菜单类型',
    show: true,
    tag: 'true',
    type: 'select',
    tagType: (tag: number) => {
      return tag === 0 ? "success" : tag === 1 ? "info" : 'danger';
    },
    tagText: (tag: number) => {
      return tag === 0 ? "目录" : tag === 1 ? "菜单" : '按钮';
    },
    selectChanged: (editCols: any, val: any) => {
      handleMenuTypeChanged(editCols, val);
    },
    options: [
      {
        value: 0,
        label: '目录'
      },
      {
        value: 1,
        label: '菜单'
      },
      {
        value: 2,
        label: '按钮'
      }
    ]
  },
  {
    id: 'component',
    name: '组件地址',
    show: false,
  },
  {
    id: 'routeName',
    name: '路由名称',
    show: false,
  },
  {
    id: 'routePath',
    name: '路由地址',
    show: false,
  },
  {
    id: 'openMode',
    name: '打开方式',
    show: true,
    tag: 'true',
    type: 'select',
    tagStyle: (tag: number) => {
      return tag === 0 ? {'color': 'green'} : {'color': '#409eff'};
    },
    tagText: (tag: number) => {
      return tag === 0 ? "新窗口" : '本页';
    },
    options: [
      {
        value: 1,
        label: '本页'
      },
      {
        value: 0,
        label: '新窗口'
      }
    ]
  },
  {
    id: 'code',
    name: '菜单编码',
    show: false,
    type: 'permit',
    inputCheck: (row: any) => {
      row.code = filterNameInput(row.code);
      if (row.code.length > 31) {
        row.code = row.code.substring(0, 31);
      }
    }
  },
  {
    id: 'hidden',
    name: '是否可见',
    show: true,
    tag: 'true',
    type: 'select',
    tagType: (tag: number) => {
      return tag === 1 ? 'danger' : 'success';
    },
    tagText: (tag: number) => {
      return tag === 1 ? "隐藏" : '可见';
    },
    options: [
      {
        value: 0,
        label: '可见'
      },
      {
        value: 1,
        label: '隐藏'
      }
    ]
  },
  {
    id: 'level',
    name: '顺序',
    show: true,
  },
  {
    id: 'icon',
    name: '菜单图标',
    show: true,
    type: 'icon',
  },
  {
    id: 'keepAlive',
    name: '缓存状态',
    show: true,
    tag: 'true',
    type: 'select',
    tagType: (tag: number) => {
      return tag === 1 ? 'success' : 'danger';
    },
    tagText: (tag: number) => {
      return tag === 1 ? '缓存' : '不缓存';
    },
    options: [
      {
        value: 1,
        label: '缓存'
      },
      {
        value: 0,
        label: '不缓存'
      }
    ]
  },
  {
    id: 'operation',
    name: '操作',
    show: true,
    hideCol: true,
    canEdit: false,
    fixed: 'right',
    buildOperations: (row: any) => {
      return buildMenuOperations(row);
    },
  }
]);

const addMenu = () => {
  currentItem.value = newMenu();
  columns.value[3].readOnly = false;
  columns.value[3].options = getMenuTypeOptions(true);

  handleMenuTypeChanged(columns.value, currentItem.value.menuType);

  refEditDlg.value?.editAdd('新增菜单', currentItem.value);
}

defineExpose({
  refresh,
})

</script>

<style scoped>
.el-form-item-class .el-form-item__label {
  font-size: 12px;
}

</style>
